package com.ruoyi.activiti.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.activiti.domain.*;
import com.ruoyi.activiti.mapper.TaskMapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
public class ActivitiConvertService {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private MyTaskService myTaskService;
    @Autowired
    TaskMapper taskMapper;

    public MyProcessDefinition convertProcessDefinition(ProcessDefinition processDefinition, boolean cascade){
        ProcessDefinitionEntityImpl entityImpl = (ProcessDefinitionEntityImpl) processDefinition;
        MyProcessDefinition entity = new MyProcessDefinition();
        entity.setId(entityImpl.getId());
        entity.setKey(entityImpl.getKey());
        entity.setName(entityImpl.getName());
        entity.setCategory(entityImpl.getCategory());
        entity.setVersion(entityImpl.getVersion());
        entity.setDescription(entityImpl.getDescription());
        entity.setDeploymentId(entityImpl.getDeploymentId());
        entity.setDiagramResourceName(entityImpl.getDiagramResourceName());
        entity.setResourceName(entityImpl.getResourceName());
        entity.setSuspendState(entityImpl.getSuspensionState() + "");
        if (entityImpl.getSuspensionState() == 1) {
            entity.setSuspendStateName("已激活");
        } else {
            entity.setSuspendStateName("已挂起");
        }
        if(cascade){//级联查询
            Deployment deployment = repositoryService.createDeploymentQuery()
                    .deploymentId(entityImpl.getDeploymentId())
                    .singleResult();
            entity.setDeploymentTime(deployment.getDeploymentTime());
        }
        return entity;
    }

    public MyProcessInstance convertProcessInstance(HistoricProcessInstance processInstance, boolean cascade){
        MyProcessInstance myProcInst = new MyProcessInstance();
        BeanUtils.copyProperties(processInstance, myProcInst);
        myProcInst.setProcessInstanceId(processInstance.getId());
        myProcInst.setProcessInstanceName(processInstance.getName());
        myProcInst.setBusinessKey(processInstance.getBusinessKey());
        myProcInst.setProcessDefinitionId(processInstance.getProcessDefinitionId());
        myProcInst.setDeploymentId(processInstance.getDeploymentId());
        myProcInst.setStartTime(processInstance.getStartTime());
        myProcInst.setEndTime(processInstance.getEndTime());
        myProcInst.setStartUserName(processInstance.getStartUserId());
        R<SysUser> r = remoteUserService.loadCachedUserByUsername(processInstance.getStartUserId());
        SysUser sysUser = r==null? null: r.getData();
        if(sysUser!=null){
            myProcInst.setStartUserNickName(sysUser.getNickName());
        }
        if(cascade){
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(processInstance.getProcessDefinitionId())
                    .singleResult();
            MyProcessDefinition myProcessDefinition = this.convertProcessDefinition(processDefinition, true);//直接级联查询
            myProcInst.setProcessDefinition(myProcessDefinition);
            myProcInst.setProcessDefinitionName(myProcessDefinition.getName());
            myProcInst.setDeploymentId(myProcessDefinition.getDeploymentId());
        }
        //填充发起人和发起时间
        if(sysUser!=null){
            myProcInst.setStartUserName(sysUser.getUserName()==null?"-":sysUser.getUserName());
            myProcInst.setStartUserNickName(sysUser.getNickName()==null?"-":sysUser.getNickName());
        }
        //填充是否完结
        myProcInst.setEnded(processInstance.getEndTime()!=null);
        //未完成的需填充任务
        if(!myProcInst.isEnded()){
            TaskCondition taskCondition = new TaskCondition();
            taskCondition.setInstanceId(processInstance.getId());
            myProcInst.setTasks(myTaskService.taskList(taskCondition));
        }
        //构造节点字符串
        if(myProcInst.isEnded()){
            myProcInst.setState("已结束，结束时间：" + DateUtil.formatDateTime(myProcInst.getEndTime()));
        }else{
            if(CollectionUtil.isEmpty(myProcInst.getTasks())){
                myProcInst.setState("无可理任务");
            }else{
                String str = "";
                int i = 0;
                for (TaskVo task : myProcInst.getTasks()) {
                    if(i>0){
                        str += "\r\n" + task.getTaskName() + "("+task.getState()+")";
                    }else{
                        str += task.getTaskName() + "("+task.getState()+")";
                    }
                    i++;
                }
                myProcInst.setState(str);
            }
        }
        return myProcInst;
    }

    public List<MyProcessInstance> convertProcessInstanceList(List<HistoricProcessInstance> procInsts, boolean cascade){
        if(CollectionUtil.isEmpty(procInsts)){
            return new ArrayList<>(0);
        }
        List<MyProcessInstance> list = new ArrayList<>(procInsts.size());
        procInsts.forEach(processInstance -> list.add(this.convertProcessInstance(processInstance, cascade)));
        return list;
    }

    public void fillTaskVo(TaskVo taskVo) {
        //fillFormData(taskVo);//填充表单
        if("1".equals(taskVo.getSuspendState())){//填充任务状态
            taskVo.setSuspendStateName("已激活");
        }else if("2".equals(taskVo.getSuspendState())){
            taskVo.setSuspendStateName("已挂起");
        }
        //填充任务处理人
        if(StringUtils.isNotEmpty(taskVo.getAssignee())){//已有处理人的情况
            R<SysUser> r = remoteUserService.loadCachedUserByUsername(taskVo.getAssignee());
            SysUser sysUser = r==null? null: r.getData();
            if(sysUser!=null){
                taskVo.addAssignee(TaskAssignee.newUserAssignee(sysUser.getUserName(), sysUser.getNickName(), true));
            }
        }else{//如无处理人则查询候选人或候选组
            Set<SysUser> users = taskMapper.queryTaskCandidateUsers(taskVo.getTaskId());
            if(CollectionUtil.isNotEmpty(users)){
                users.forEach(user -> taskVo.addAssignee(
                        TaskAssignee.newUserAssignee(user.getUserName(), user.getNickName(), false)));
            }
            Set<SysRole> roles = taskMapper.queryTaskCandidateGroups(taskVo.getTaskId());//获取任务关联的组列表
            if(CollectionUtil.isNotEmpty(roles)){
                roles.forEach(role -> taskVo.addAssignee(
                        TaskAssignee.newGroupAssignee(role.getRoleKey(), role.getRoleName(), false)));
            }
        }
        //格式化state
        if(CollectionUtil.isEmpty(taskVo.getTaskAssignees())){
            taskVo.setState("无处理人");
        }else{
            String str = "";
            int i = 0;
            for (TaskAssignee taskAssignee : taskVo.getTaskAssignees()) {
                if(i>0){
                    str += "、";
                }
                if("USER".equals(taskAssignee.getAssigneeType())){
                    str += taskAssignee.getUserNickname();
                }else if("GROUP".equals(taskAssignee.getAssigneeType())){
                    str += "["+taskAssignee.getGroupName()+"]";
                }
            }
            str += " 处理中";
            taskVo.setState(str);
        }
    }

}
